package com.apes.framework.plugin.soe.store.database.service;

import com.apes.framework.api.DomainService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.soe.metadata.*;
import com.apes.framework.plugin.soe.store.database.repository.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 功能：场景实例服务
 *
 * @author xul
 * @create 2018-09-25 17:44
 */
@Service
public class SceneInstanceService extends DomainService {

    @Autowired
    SceneRepository sceneRepository;

    @Autowired
    BusinessTypeRepository businessTypeRepository;

    @Autowired
    SceneInstanceRepository instanceRepository;

    @Autowired
    SceneInstanceRoleRepository instanceRoleRepository;

    @Autowired
    SceneInstanceFlowRepository instanceFlowRepository;

    @Autowired
    private SceneInstanceVariableRepository sceneInstanceVariableRepository;

    @Autowired
    private BusinessTypeService businessTypeService;

    public SceneInstance createSceneInstance(Scene scene) {
        SceneInstance sceneInstance = new SceneInstance();
        sceneInstance.setScene(scene);
        return instanceRepository.saveAndFlush(sceneInstance);
    }

    public void finishedSceneInstance(SceneInstance sceneInstance) {
        sceneInstance.setFinished(true);
        instanceRepository.saveAndFlush(sceneInstance);
    }

    public void suspendSceneInstanceById(String sceneInstanceId) {
        SceneInstance sceneInstance = instanceRepository.findOne(sceneInstanceId);
        sceneInstance.setSuspend(true);
        instanceRepository.saveAndFlush(sceneInstance);
    }

    public void activateSceneInstanceById(String sceneInstanceId) {
        SceneInstance sceneInstance = instanceRepository.findOne(sceneInstanceId);
        if (!sceneInstance.isSuspend()) throw new RuntimeException("场景实例：" + sceneInstance.getId() + " 未挂起，不允激活");
        sceneInstance.setSuspend(false);
        instanceRepository.saveAndFlush(sceneInstance);
    }

    public SceneInstance sceneInstanceService(String sceneInstanceId) {
        return instanceRepository.findOne(sceneInstanceId);
    }

    public SceneInstance findSceneInstance(String sceneId, String businessTypeId, String businessKey) {
        SceneInstanceRole sceneInstanceRole = instanceRoleRepository.findFirstBySceneIdAndBusinessTypeIdAndBusinessKey(sceneId, businessTypeId, businessKey);
        if (sceneInstanceRole == null) return null;
        return sceneInstanceRole.getSceneInstance();
    }

    public SceneInstance findSceneInstance(Scene scene, BusinessType businessType, String businessKey) {
        SceneInstanceRole sceneInstanceRole = instanceRoleRepository.findBySceneAndBusinessTypeAndBusinessKey(scene, businessType, businessKey);
        if (sceneInstanceRole == null) return null;
        return sceneInstanceRole.getSceneInstance();
    }

    public List<SceneInstanceFlow> findSceneInstanceFlow(String sceneInstanceId, String sceneFlowId) {
        return instanceFlowRepository.findAllBySceneInstanceIdAndSceneFlowId(sceneInstanceId, sceneFlowId);
    }

    public List<SceneInstanceFlow> findSceneInstanceFlow(SceneInstance sceneInstance, SceneFlow sceneFlow) {
        return instanceFlowRepository.findAllBySceneInstanceAndSceneFlow(sceneInstance, sceneFlow);
    }

    public SceneInstanceFlow createSceneInstanceFlow(SceneInstance sceneInstance, SceneFlow sceneFlow) {
        if (sceneInstance.isSuspend()) throw new RuntimeException("场景实例：" + sceneInstance.getId() + " 已挂起，不允许操作");
        SceneInstanceFlow instanceFlow = new SceneInstanceFlow();
        instanceFlow.setSceneInstance(sceneInstance);
        instanceFlow.setSceneFlow(sceneFlow);
        instanceFlow.setAuto(sceneFlow.isAuto());
        instanceFlow.setStep(sceneFlow.getStep());
        return instanceFlowRepository.saveAndFlush(instanceFlow);
    }

    public SceneInstanceRole createSceneInstanceRole(SceneInstance sceneInstance, String businessTypeId, String businessKey) {
        BusinessType businessType = businessTypeRepository.findOne(businessTypeId);
        if (businessType == null) throw new RuntimeException("凭证类型编码：" + businessTypeId + " 错误");
        return createSceneInstanceRole(sceneInstance, businessType, businessKey);
    }

    public SceneInstanceRole createSceneInstanceRole(SceneInstance sceneInstance, BusinessType businessType, String businessKey) {
        if (sceneInstance.isSuspend()) throw new RuntimeException("场景实例：" + sceneInstance.getId() + " 已挂起，不允许操作");
        SceneInstanceRole sceneInstanceRole = instanceRoleRepository.findBySceneAndBusinessTypeAndBusinessKey(sceneInstance.getScene(), businessType, businessKey);
        if (sceneInstanceRole != null) return sceneInstanceRole;
        sceneInstanceRole = new SceneInstanceRole();
        sceneInstanceRole.setSceneInstance(sceneInstance);
        sceneInstanceRole.setScene(sceneInstance.getScene());
        sceneInstanceRole.setBusinessType(businessType);
        sceneInstanceRole.setBusinessKey(businessKey);
        return instanceRoleRepository.saveAndFlush(sceneInstanceRole);
    }

    /**
     * 设置场景变量
     **/
    public void setSceneInstanceVariable(Scene scene, String businessTypeName, String businessKey, String name, String text) {
        if (scene == null) {
            return;
        }
        BusinessType businessType = businessTypeService.getBusinessTypeByCache(businessTypeName);
        if (businessType == null) {
            throw new RuntimeException("凭证类型：" + businessTypeName + " 未定义！");
        }
        SceneInstance sceneInstance = findSceneInstance(scene, businessType, businessKey);
        if (sceneInstance == null) {
            return;
        }
        setSceneInstanceVariable(sceneInstance, name, text);
    }

    /**
     * 设置场景变量
     **/
    public void setSceneInstanceVariable(SceneInstance sceneInstance, String name, String text) {
        SceneInstanceVariable sceneInstanceVariable = sceneInstanceVariableRepository.findOne(JpaDsl.toCriteriaByEq("sceneInstance", sceneInstance, "name", name)).orElse(null);
        if (sceneInstanceVariable == null) {
            sceneInstanceVariable = new SceneInstanceVariable();
            sceneInstanceVariable.setSceneInstance(sceneInstance);
            sceneInstanceVariable.setName(name);
        }
        sceneInstanceVariable.setText(text);
        sceneInstanceVariableRepository.saveAndFlush(sceneInstanceVariable);
    }
}
